
static FileDesc* _NewFileDesc(int fd, const UEventFileDescDetail *detail) {
    FileDesc* ptr = (FileDesc*) malloc(sizeof(FileDesc));
    if (ptr != NULL) {
        ptr->fd = fd;
        memcpy(&ptr->detail, detail, sizeof(UEventFileDescDetail));
        ptr->is_deleted = false;
    }
    return ptr;
}

static void _DeleteFileDesc(FileDesc *file_desc) {
    free(file_desc);
}

static void _FreeFunc_DeleteFileDesc(void *p) {
    FileDesc *item = (FileDesc*)p;
    _DeleteFileDesc(item);
}

static bool _CondFunc_IsFileDescFDMatch(void *p, void *a) {
    FileDesc *item = (FileDesc*)p;
    int fd = *(int*)a;
    return (item->fd == fd);
}

/**
 * \brief   在UEventLoop中查找fd对应的文件描述符
 *
 * 首先在 file_descs 中找，如果没有找到则在 file_descs_tobe 中找
 */
static FileDesc* _FindFileDescByFD(UEventLoop *loop, int fd) {
    int pos = PtrVector_Find(loop->file_descs, _CondFunc_IsFileDescFDMatch, &fd, 0);
    if (pos >= 0)
        return (FileDesc*)PtrVector_GetAt(loop->file_descs, pos);

    pos = PtrVector_Find(loop->file_descs_tobe, _CondFunc_IsFileDescFDMatch, &fd, 0);
    if (pos >= 0)
        return (FileDesc*)PtrVector_GetAt(loop->file_descs_tobe, pos);

    return NULL;
}

UEventRetCode UEvent_ReadFileDescDetail(UEventLoop *loop, int fd, UEventFileDescDetail *detail) {
    if (loop == NULL || detail == NULL || fd < 0)
        return kUEventInvalidArgument;

    FileDesc *file_desc = _FindFileDescByFD(loop, fd);
    if (file_desc == NULL)
        return kUEventFileDescNotExist;

    memcpy(detail, &file_desc->detail, sizeof(UEventFileDescDetail));
    return kUEventOK;
}

UEventRetCode UEvent_UpdateFileDesc(UEventLoop *loop, int fd, const UEventFileDescDetail *detail) {
    if (loop == NULL || detail == NULL || fd < 0)
        return kUEventInvalidArgument;

    //! 确保detail中的设置是有意义的
    if (detail->operation_bits == kUEventOperationNone || detail->callback_func == NULL)
        return kUEventInvalidArgument;


    FileDesc* file_desc = _FindFileDescByFD(loop, fd);
    if (file_desc == NULL) {
        file_desc = _NewFileDesc(fd, detail);
        if (file_desc == NULL)
            return kUEventOutOfMemery;

        if (loop->executing_fd_callback) {
            PtrVector_PushBack(loop->file_descs_tobe, file_desc);
        } else {
            PtrVector_PushBack(loop->file_descs, file_desc);
        }
    } else {
        memcpy(&file_desc->detail, detail, sizeof(UEventFileDescDetail));
    }

    _Wakeup(loop);

    return kUEventOK;
}

UEventRetCode UEvent_RemoveFileDesc(UEventLoop *loop, int fd) {
    if (loop == NULL || fd <= 0)
        return kUEventInvalidArgument;

    FileDesc* file_desc = _FindFileDescByFD(loop, fd);
    if (file_desc == NULL)
        return kUEventFileDescNotExist;

    file_desc->is_deleted = true;
    _Wakeup(loop);

    return kUEventOK;
}
